﻿using System;
using GcTrackableRace.Entities;
using GCTrackableRace.Interfaces;
using System.Net;
using System.Xml;

namespace GcTrackableRace.RemoteServices
{
	public class RemoteService : IRemoteService
	{
		private const string _Url = "http://maps.googleapis.com/maps/api/geocode/xml?latlng={0},{1}&sensor=false";

		public ILocationInfo GetLocationInfo(double? latitude, double? longitude)
		{
			if (latitude == null || longitude == null)
			{
				return new LocationInfo();
			}

			WebResponse response;

			try
			{
				var request = (HttpWebRequest) WebRequest.Create(string.Format(_Url, latitude, longitude));

				request.Method = "GET";

				response = request.GetResponse();
			}
			catch (Exception ex)
			{
				Console.WriteLine("  ERROR:" + ex.Message);
				return new LocationInfo();
			}

			XmlDocument doc = new XmlDocument();

			doc.Load(response.GetResponseStream());

			string countryCode;
			string countryName;
			string stateName;
			string stateCode;
			string area;
			string postalCode;

			if (doc.SelectNodes("/GeocodeResponse/result[type='country']").Count > 0)
			{
				// Country
				countryCode = doc.SelectSingleNode("/GeocodeResponse/result[type='country']/address_component/short_name").InnerText;
				countryName = doc.SelectSingleNode("/GeocodeResponse/result[type='country']/address_component/long_name").InnerText;

				// State / Province Name / Code
				if (doc.SelectNodes("/GeocodeResponse/result[type='administrative_area_level_1']").Count > 0)
					stateName = doc.SelectSingleNode("/GeocodeResponse/result[type='administrative_area_level_1']/address_component/long_name").InnerText;
				else
					stateName = null;

				if (doc.SelectNodes("/GeocodeResponse/result[type='administrative_area_level_1']").Count > 0)
					stateCode = doc.SelectSingleNode("/GeocodeResponse/result[type='administrative_area_level_1']/address_component/short_name").InnerText;
				else
					stateCode = null;

				// Area
				if (doc.SelectNodes("/GeocodeResponse/result[type='locality']/address_component[type='locality']").Count > 0)
					area =
						doc.SelectSingleNode("/GeocodeResponse/result[type='locality']/address_component[type='locality']/long_name").
							InnerText;
				else
					area = null;

				// Postal Code
				if (doc.SelectNodes("/GeocodeResponse/result[type='postal_code']/address_component[type='postal_code']").Count > 0)
					postalCode = doc.SelectSingleNode("/GeocodeResponse/result[type='postal_code']/address_component[type='postal_code']/long_name").InnerText;
				else
					postalCode = null;
			}
			else
			{
				var countryCodeDoc = doc.SelectSingleNode("/GeocodeResponse/result[type='street_address']/address_component[type='country']/short_name");
				countryCode = countryCodeDoc != null ? countryCodeDoc.InnerText : null;

				var countryNameDoc = doc.SelectSingleNode("/GeocodeResponse/result[type='street_address']/address_component[type='country']/long_name");
				countryName = countryNameDoc != null ? countryNameDoc.InnerText : null;

				var stateCodeDoc = doc.SelectSingleNode("/GeocodeResponse/result[type='street_address']/address_component[type='administrative_area_level_1']/short_name");
				stateCode = stateCodeDoc != null ? stateCodeDoc.InnerText : null;

				var stateNameDoc = doc.SelectSingleNode("/GeocodeResponse/result[type='street_address']/address_component[type='administrative_area_level_1']/long_name");
				stateName = stateNameDoc != null ? stateNameDoc.InnerText : null;

				var areaDoc = doc.SelectSingleNode("/GeocodeResponse/result[type='street_address']/address_component[type='locality']/long_name");
				area = areaDoc != null ? areaDoc.InnerText : null;

				var postalCodeDoc = doc.SelectSingleNode("/GeocodeResponse/result[type='street_address']/address_component[type='postal_code']/long_name");
				postalCode = postalCodeDoc != null ? postalCodeDoc.InnerText : null;
			}

			return new LocationInfo
				{
					Area = area,
					CountryCode = countryCode,
					CountryName = countryName,
					StateName = stateName,
					StateCode = stateCode,
					Latitude = latitude,
					Longitude = longitude,
					PostalCode = postalCode
				};
		}
	}
}